class_name Player
extends CharacterBody2D

@export var random_skins: Array[Color] = []
@export var skin_data_initialized := 0
@export var skin_data: Dictionary[String, Color]
@export var shader_material: ShaderMaterial

@export var auto_move := false
@export var speed := 60.0
@export var knockback_force := 240.0
@export var dash_mul := 1.8
@export var dash_knockback_mul := 1.4
@export var max_health: float = 20.0
@export var health: float
@export var damage: float = 2.0
@export var animated_sprite: AnimatedSprite2D
@export var animation_player: AnimationPlayer
@export var body_coll: CollisionShape2D
@export var attack_coll: CollisionShape2D
@export var sword_sprite: Sprite2D
@export var foot_dust: Node2D
@export var foot_dust_particle: GPUParticles2D
@export var s_fda_r = 0.4
@export var min_ar_rate = 0.1
var min_ar: float:
	get:return s_fda_r * min_ar_rate
	#set(value):min_ar = value

@export var hurt_area: Area2D
@export var player_name_label: Label
func player_name() -> String: return player_name_label.text
# 常用的中文游戏ID
var name_list := [
	"神秘玩家", "风暴骑士", "雷霆战士", "幽灵 assassin", "龙之影", "火焰剑士",
	"光明使者", "黑暗降临", "刀锋战士", "铁血勇士", "战神", "孤独王者", "流浪猎手",
	"暗夜杀手", "天空守护", "猎魔人", "苍穹之翼", "剑破九天", "烈焰炎龙", "雪域孤狼"
]

var cur_state: String = "idle"
@export var is_dashing := false
@export var ban_input := false
@export var attack_dir := Vector2(0, 0)

@export var victim_list: Array[Player] = []
@export var attack_coll_start_offset: Vector2

func _ready() -> void:
	if is_multiplayer_authority():
		health = max_health
		attack_coll_start_offset = attack_coll.position
		init_local_player()
		spawn()
	#hurt.rpc(20)
	pass

func _process(delta: float) -> void:
	# 未连接则阻止操作
	if multiplayer.multiplayer_peer == null: return
	if !OS.has_feature("dedicated_server"):
		init_self_skin()
	# 非本地玩家则无权操作
	if !is_multiplayer_authority(): return
	
	## 同步皮肤数据
	#if skin_data_initialized == 1:
		#init_self_skin()
	# 播放疾跑灰尘
	play_foot_dust()
	# 获取输入方向
	var dir = Input.get_vector("move_left", "move_right", "move_up", "move_down")
	handle_dashing()
	# 自动奔跑
	if Input.is_action_just_pressed("auto_move"):
		auto_move = !auto_move
	if auto_move: 
		dir = attack_dir if dir.is_zero_approx() else dir
	#if dir != Vector2.ZERO: print("输入方向: ", dir)
	#dir = dir.normalized()
	var vel = dir * speed * dash_vel()
	# 翻转人物
	if dir.x > 0:
		animated_sprite.flip_h = false
		#attack_coll.rotation = deg_to_rad(-90)
		foot_dust.scale.x = 1
	if dir.x < 0:
		animated_sprite.flip_h = true
		foot_dust.scale.x = -1
		#attack_coll.rotation = deg_to_rad(90)
	# 待机与移动动画
	if cur_state != "attack" and cur_state != "hurt": 
		if dir.is_zero_approx():
			animation_player.play("idle")
		else:
			animation_player.play("run")
	# 攻击动画
	if !dir.is_zero_approx(): 
		attack_dir = dir
	if Input.is_action_just_pressed("attack"):
		animation_player.play("attack")
		cur_state = "attack"
	
	# 调整攻击方向
	var attack_rad = attack_dir.angle()
	var attack_angle = rad_to_deg(attack_rad)
	var dir_offset = attack_coll_start_offset.rotated(attack_rad)
	#LogLabel.print_log(["角度: ", attack_angle])
	sword_sprite.rotation = deg_to_rad(attack_angle)
	attack_coll.rotation = deg_to_rad(attack_angle)
	attack_coll.position = dir_offset
	# 应用位置
	#position += vel
	
	# 应用移动
	velocity = velocity.move_toward(Vector2.ZERO, 20 * delta * 60) # 摩擦力
	if dir and cur_state != "attack" and cur_state != "hurt":
		if !ban_input: 
			velocity = vel
		#velocity = velocity.move_toward(Vector2.ZERO, speed)
	move_and_slide()

var down_index := 0
var last_dash_dir := ""
var just_down := false
var double_interval := 0.2
var last_key_time: float
func handle_dashing():
	if !is_dashing and Input.is_action_pressed("dash"):
		is_dashing = true
		print("按下shift, 进入冲刺")
		pass
	elif is_dashing and Input.is_action_just_released("dash"): 
		is_dashing = false
		print("抬起shift, 退出冲刺")
		pass
	var current_time = Time.get_ticks_msec() / 1000.0
	var key_down := false
	var dash_dir := ""
	if Input.is_action_pressed("move_left"):
		dash_dir = "move_left"
	if Input.is_action_pressed("move_right"):
		dash_dir = "move_right"
	if Input.is_action_pressed("move_up"):
		dash_dir = "move_up"
	if Input.is_action_pressed("move_down"):
		dash_dir = "move_down"
	key_down = dash_dir != ""
	var key_up = !key_down
	if down_index == 0:
		if key_down:
			last_key_time = current_time
			#print("首次按下", last_key_time)
			get_tree().create_timer(double_interval).timeout.connect(_double_click_timeout)
			down_index = 1
		pass
	if down_index == 1:
		if key_up: 
			#print("首次抬起", )
			down_index = 2
		pass
	pass
	if down_index == 2:
		if key_down: 
			#print("二次按下", current_time)
			var time_diff = current_time - last_key_time
			var in_double_time = time_diff <= double_interval
			#print("在双击间隔内", in_double_time, ", ", time_diff)
			var same_key = last_dash_dir == dash_dir
			#print("同键", same_key, ", ", last_dash_dir, ", ", dash_dir)
			if in_double_time and same_key:
				is_dashing = true
				print("双击成功, 进入冲刺")
			down_index = 3
		pass
	pass
	if down_index == 3:
		if key_up: 
			#print("二次抬起", current_time)
			if is_dashing:
				print("抬起方向键, 退出冲刺")
				is_dashing = false
			down_index = 0
		pass
	pass
	if dash_dir != "": last_dash_dir = dash_dir

func _double_click_timeout():
	if !is_dashing:
		#print("down_index置0")
		down_index = 0
	pass

func dash_vel()->float:
	return dash_mul if is_dashing else 1.0
func dash_knockback_vel()->float:
	return dash_knockback_mul if is_dashing else 1.0


func _enter_tree() -> void:
	# 设置节点多人权限
	set_multiplayer_authority(name.to_int())


func spawn():
	# 随机选择中文游戏ID
	var rand = randi()
	var random_name = name_list[rand % name_list.size()]
	random_name += str(randi_range(0, 999))
	player_name_label.text = random_name  # 设置 Label 上的玩家名
	LogLabel.print_log(["玩家名称: ", random_name])
	
	# 随机玩家皮肤色
	skin_data["hat"] = random_skins[randi() % random_skins.size()]
	skin_data["cape"] = random_skins[randi() % random_skins.size()]
	#skin_data_initialized = 1
	#init_player_skin.rpc(GameControl.instance.local_uuid, skin_data)
	
	# 出生位置
	spawn_pos()
	pass

func spawn_pos() -> void:
	# 设置出生点
	var range := 500
	position = Vector2(500, 300) + Vector2(randf_range(-range, range), randf_range(-range, range))
	var window_size = get_viewport().get_size()
	var world_scl = GameControl.instance.world.scale
	var margin = 100
	var min_pos = Vector2(margin, margin)
	var max_pos = Vector2(window_size.x / world_scl.x - margin, window_size.y / world_scl.y - margin)
	position = position.clamp(min_pos, max_pos)
	position = GameControl.instance.player_spawn_point.position
	LogLabel.print_log(["玩家出生坐标: ", position])
	pass


func init_self_skin():
	shader_material = animated_sprite.material as ShaderMaterial
	shader_material.set_shader_parameter("hat_color", skin_data["hat"])
	shader_material.set_shader_parameter("cape_color", skin_data["cape"])
	skin_data_initialized = 2
	pass

@rpc("authority", "call_local", "reliable")
func init_local_player() -> void: 
	# 非本地玩家无需理会
	if !is_multiplayer_authority(): return
	# 绑定本地玩家
	GameControl.instance.local_player = self
	# 相机绑定
	GameControl.instance.world_cam.init_target(self)

@rpc("any_peer", "call_local", "reliable")
func init_player_skin(id: int, skin_data: Dictionary[String, Color]):
	if OS.has_feature("dedicated_server"): return
	if id == name.to_int():
		var local_player = GameControl.instance.local_player
		print("[本地端-", "" if local_player == null else local_player.player_name(), "]: ", "玩家", player_name_label.text, "设置皮肤: ", skin_data)
		shader_material = animated_sprite.material as ShaderMaterial
		shader_material.set_shader_parameter("hat_color", skin_data["hat"])
		shader_material.set_shader_parameter("cape_color", skin_data["cape"])
	pass

@rpc("authority", "call_local", "reliable")
func send_msg_rpc(local_uuid: String, name: String, msg: String):
	var full_msg = name+": "+msg
	#print(full_msg)
	LogLabel.print_msg([full_msg])
	pass

@rpc("authority", "call_local", "reliable")
func knockback_player(knockback: Vector2) -> void:
	#if id != name.to_int(): return
	var local_player = GameControl.instance.local_player
	print("[本地端-", "" if local_player == null else local_player.player_name(), "]: ", "玩家", player_name_label.text, "被击退: ", knockback)
	velocity = knockback

@rpc("authority", "call_local", "reliable")
func erase_player() -> void:
	var local_player = GameControl.instance.local_player
	print("[本地端-", "" if local_player == null else local_player.player_name(), "]: ", "玩家", player_name(), "被擦除")
	visible = false
	pass

@rpc("authority", "call_local", "reliable")
func hurt(damage: float) -> void:
	#if id != name.to_int(): return
	#if self != GameControl.instance.local_player: return
	if cur_state == "death": return
	var player_name = player_name_label.text
	var later_health = self.health - damage
	if later_health <= 0: 
		print("玩家", player_name, "死亡")
		ban_input = true
		cur_state = "death"
		animation_player.play("death")
		self.health = 0
		return
	else:
		print("玩家", player_name, "被伤害: ", damage, "剩余血量: ", later_health)
		#ban_input = true
		cur_state = "hurt"
		animation_player.play("hurt")
		self.health = later_health
	pass

func _on_animation_finished(anim_name: String):
	#var anim_name = animated_sprite.animation
	if anim_name == "attack":  # 确保是 attack 动画结束时
		animation_player.play("idle")  # 切换到 idle 动画
		cur_state = "idle"
	if anim_name == "hurt":
		animation_player.play("idle")
		cur_state = "idle"
		#ban_input = false
	if anim_name == "death":
		erase_player()
		if self == GameControl.instance.local_player: 
			GameControl.instance.show_die_panel()

@rpc("any_peer", "call_remote", "reliable")
func ping_request(sender: int, start_ms: int):
	ping_receive.rpc_id(sender, start_ms)
	pass
@rpc("any_peer", "call_remote", "reliable")
func ping_receive(start_ms: int):
	var current_ms = Time.get_unix_time_from_system() * 1000
	var spend_ms = current_ms - start_ms
	var ping = GameControl.instance.get_cur_ping(spend_ms)
	pass


func _on_hurt_area_body_entered(other: Node2D) -> void:
	if other != self and other is Player:
		var other_id = other.name.to_int()
		var other_name = other.player_name_label.text
		var self_name = player_name_label.text
		
		# 如果已在受害者列表则忽略
		if victim_list.find(other) != -1:
			print("目标已受害过, 返回")
			return
		# 记录已触发伤害的受害者
		else:
			victim_list.append(other)
			print(other_name, "加入到已受害列表")
		
		#print(other.player_name_label.text, "身体被: ", player_name_label.text, "剑所伤")
		# 获取击退方向（从碰撞位置指向自身中心）
		#var knockback_direction = (other.global_position - self.global_position).normalized()
		var knockback_direction = attack_dir # 改为剑的方向
		print("击退方向: ", knockback_direction)
		# 设置击退力度，可以调整数值使击退更明显
		# 应用击退效果
		print("击退倍率: ", dash_knockback_vel())
		var knockback_vel = knockback_direction * knockback_force * dash_knockback_vel()
		other.knockback_player(knockback_vel)
		
		# 扣血
		other.hurt(damage)
	pass


func _on_hurt_area_body_exited(other: Node2D) -> void:
	if other != self and other is Player and victim_list.find(other) != -1:
		var other_name = other.player_name_label.text
		# 当退出时释放已触发伤害的受害者
		victim_list.erase(other)
		print(other_name, "从已受害列表移除")
	pass # Replace with function body.


func respawn() -> void:
	visible = true
	spawn_pos()
	ban_input = false
	health = max_health
	velocity = Vector2.ZERO
	cur_state = "idle"
	animation_player.play("idle")
	pass


func play_foot_dust():
	var play_foot_dust = animation_player.current_animation == "run" and is_dashing
	foot_dust_particle.emitting = play_foot_dust
	var val = velocity.length() / speed * s_fda_r
	if val < min_ar: val = s_fda_r
	foot_dust_particle.amount_ratio = val
	pass
